<html>
<head><meta charset="utf-8"><title>Internals of repr(C) · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html">Internals of repr(C)</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="238312736"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238312736" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238312736">(May 11 2021 at 14:03)</a>:</h4>
<p>Hi everyone, I'm wondering how <code>repr(C)</code> works under the hood. I understand it uses the C ABI of the platform that you're compiling for. How does the compiler know about this? Does it use something like libclang, or relying on LLVM, or something else?</p>
<p>(I tried searching through the streams but I didn't find the exact answer)</p>



<a name="238313214"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238313214" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238313214">(May 11 2021 at 14:05)</a>:</h4>
<p>(also feel free to redirect me to the most appropriate stream to discuss this if general is the wrong place to ask this)</p>



<a name="238313403"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238313403" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jonas Schievink  [he/him] <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238313403">(May 11 2021 at 14:06)</a>:</h4>
<p>I think it uses a mixture of implementing the C ABI in rustc, and relying on LLVM to get the calling convention right</p>



<a name="238313475"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238313475" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Steven Fackler <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238313475">(May 11 2021 at 14:07)</a>:</h4>
<p>That's included in the definition of a target in rustc itself: <a href="https://github.com/rust-lang/rust/blob/125505306744a0a5bb01d62337260a95d9ff8d57/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs">https://github.com/rust-lang/rust/blob/125505306744a0a5bb01d62337260a95d9ff8d57/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs</a></p>



<a name="238314065"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238314065" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238314065">(May 11 2021 at 14:11)</a>:</h4>
<p>I see, thank you for the pointers</p>



<a name="238314497"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238314497" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238314497">(May 11 2021 at 14:13)</a>:</h4>
<p>So, If I understand correctly it uses the <code>data_layout</code> attr along with something like <a href="https://doc.rust-lang.org/reference/type-layout.html#reprc-structs">https://doc.rust-lang.org/reference/type-layout.html#reprc-structs</a> to build the struct?</p>



<a name="238333758"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238333758" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Steven Fackler <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238333758">(May 11 2021 at 16:01)</a>:</h4>
<p>Yep.</p>



<a name="238335426"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238335426" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238335426">(May 11 2021 at 16:10)</a>:</h4>
<p>Great, thanks. Do you also perform any checks for struct values coming from C? Do you assume that whatever C shared library the user is interfacing with will have the same ABI / calling convention as the platform you're compiling in?</p>



<a name="238335889"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238335889" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238335889">(May 11 2021 at 16:13)</a>:</h4>
<p>The overall context of my questions is wondering how Rust deals with pass-by-value structs in the FFI. For example, if a C returns a struct, Rust should know how the layout of that struct, somehow. Or, if the C library performs rvo on the struct, how does Rust know?</p>



<a name="238341822"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238341822" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238341822">(May 11 2021 at 16:53)</a>:</h4>
<p>You can't perform RVO and adhere to the ABI. That's rather the point of an ABI.</p>



<a name="238341890"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238341890" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238341890">(May 11 2021 at 16:53)</a>:</h4>
<p>Unless "RVO" were baked into the ABI, in which case it'd be a part of the definition of the ABI.</p>



<a name="238342027"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238342027" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238342027">(May 11 2021 at 16:54)</a>:</h4>
<p>So, yes, you need to define the struct using equivalent layouts in both languages.</p>



<a name="238342197"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238342197" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238342197">(May 11 2021 at 16:56)</a>:</h4>
<p>You declare which ABI you want via <code>extern "Foo" fn</code>. Usually <code>"C"</code>, but there are others for less-common cases, such as 32-bit Windows variants or Linux kernel or embedded interrupt handlers.</p>



<a name="238348517"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238348517" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238348517">(May 11 2021 at 17:11)</a>:</h4>
<p>See also <code>FnAbi::adjust_for_cabi</code> <a href="https://github.com/rust-lang/rust/blob/2bafe96272bf22cd191c6a01741184b60063292d/compiler/rustc_target/src/abi/call/mod.rs#L602-L603">https://github.com/rust-lang/rust/blob/2bafe96272bf22cd191c6a01741184b60063292d/compiler/rustc_target/src/abi/call/mod.rs#L602-L603</a></p>



<a name="238349981"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238349981" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238349981">(May 11 2021 at 17:21)</a>:</h4>
<blockquote>
<p>You can't perform RVO and adhere to the ABI.</p>
</blockquote>
<p>Thanks for the clarification <span class="user-mention" data-user-id="116155">@Jake Goulding</span> . I tried searching for an answer as to whether RVO could happen across shared libraries, but didn't find a good source. Evidently my google-fu is lacking</p>



<a name="238350439"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238350439" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238350439">(May 11 2021 at 17:24)</a>:</h4>
<blockquote>
<p>So, yes, you need to define the struct using equivalent layouts in both languages.</p>
</blockquote>
<p>Does the compiler emit a warning if there's a mismatch, or does it assume that you will do it correctly?</p>



<a name="238350563"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238350563" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238350563">(May 11 2021 at 17:25)</a>:</h4>
<p>Not for shared libraries, but also check out link-time optimization (LTO)</p>



<a name="238350802"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238350802" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238350802">(May 11 2021 at 17:27)</a>:</h4>
<p>Is that re: rvo or re: compiler warnings?</p>



<a name="238351760"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238351760" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238351760">(May 11 2021 at 17:32)</a>:</h4>
<p>general concept of "optimizations across units"</p>



<a name="238351836"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238351836" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238351836">(May 11 2021 at 17:32)</a>:</h4>
<p>How would you propose such a warning would be implemented? What would you use to tell if the struct is "correct"?</p>



<a name="238351929"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238351929" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238351929">(May 11 2021 at 17:33)</a>:</h4>
<p>I'm not sure if it can be done, that's why I was asking</p>



<a name="238352526"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238352526" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238352526">(May 11 2021 at 17:37)</a>:</h4>
<p>I was looking into how Rust does FFI because I'm trying to see how to do pass-by-value with structs correctly in the Pony programming language.</p>



<a name="238352696"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238352696" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238352696">(May 11 2021 at 17:38)</a>:</h4>
<p>Someone reported that it wasn't working correctly, so it was removed from the compiler, but I'm trying to figure out how to bring pass-by-value structs back.</p>



<a name="238353410"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238353410" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238353410">(May 11 2021 at 17:43)</a>:</h4>
<p>At runtime, you just have a bag of bytes, there's no runtime type information (RTTI)</p>



<a name="238353498"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238353498" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238353498">(May 11 2021 at 17:44)</a>:</h4>
<p>at best you could inspect the C header, parse it, then generate code. Rust does that with bindgen</p>



<a name="238353544"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238353544" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238353544">(May 11 2021 at 17:44)</a>:</h4>
<p>You may also want to look at libffi, which has to deal with all sorts of this junk</p>



<a name="238353973"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238353973" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238353973">(May 11 2021 at 17:47)</a>:</h4>
<p>Pass by value is part of the calling convention. If the calling convention says no, you aren't allowed to pass structs by value. If the ABI says yes, you must pass it by value. You can have different calling conventions for different functions though. For example in Rust the default calling convention is "Rust". This calling convention is unstable and currently passes structs up to 2 registers big by value and everything else by reference. When interfacing with C you define the "C" abi, which will match the native C abi for the target you are compiling for. On some targets only simple structs wrapping a single integer are passed by value. On some targets it allows more complex structs to be passed by value and on yet other targets structs are always passed by reference.</p>



<a name="238354466"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238354466" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238354466">(May 11 2021 at 17:51)</a>:</h4>
<p>I see, thanks for the help everyone. I need to get some reading done. One thing though, how much work does LLVM do for you when it comes to this? I assumed that LLVM would take care of generating the code with the correct calling convention.</p>



<a name="238354830"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238354830" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238354830">(May 11 2021 at 17:53)</a>:</h4>
<p>The part that determines the actual register and stack locations is in LLVM. The pass by value/pass by reference logic is inside rustc itself and split out over <a href="https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/abi/call">https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/abi/call</a> and <a href="https://github.com/rust-lang/rust/blob/2bafe96272bf22cd191c6a01741184b60063292d/compiler/rustc_middle/src/ty/layout.rs#L2448-L3009">https://github.com/rust-lang/rust/blob/2bafe96272bf22cd191c6a01741184b60063292d/compiler/rustc_middle/src/ty/layout.rs#L2448-L3009</a></p>



<a name="238354908"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238354908" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238354908">(May 11 2021 at 17:54)</a>:</h4>
<blockquote>
<p>the correct calling convention</p>
</blockquote>
<p>Part of the problem is that there are many. And, as mentioned:</p>
<blockquote>
<p>For example in Rust the default calling convention is "Rust". This calling convention is unstable</p>
</blockquote>
<p>LLVM wouldn't even know what Rust's calling convention is. <span aria-label="sweat smile" class="emoji emoji-1f605" role="img" title="sweat smile">:sweat_smile:</span></p>



<a name="238355697"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238355697" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238355697">(May 11 2021 at 17:59)</a>:</h4>
<p><span class="user-mention" data-user-id="133247">@bjorn3</span> Have to go now, but will look through your links later, thanks!</p>



<a name="238355728"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Internals%20of%20repr%28C%29/near/238355728" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Borja o&#x27;Cook <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Internals.20of.20repr(C).html#238355728">(May 11 2021 at 17:59)</a>:</h4>
<p>Thanks all for your help!</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>